#import some required files
from Tkinter import *
from random import *
from time import time, sleep
from being_thread import *
from pygame import mixer

#external file containing class, "Human"
from Human import *

#external file containing class, "Zombie"
from Zombie import *

#external file containing class, "Building"
from Building import *

#external file containing class, "Player"
from Player import *

#creates instance of tkinter window and returns reference to canvas
def initialize_window(root):
	#create a canvas for our city
	canvas = Canvas(root, width=600, height=400, background="#000")
	canvas.pack(side='top')
	
	#also create a canvas to be used as the Heads-Up Display
	hud = Canvas(root, width=600, height=70, background="#222")
	hud.pack(side='bottom')
	
	#now let's create all of the required pieces of the city...
	
	#create the buildings
	buildings = build_city(50,canvas)
	
	#create zombies
	zombies = place_zombies(25,canvas,root,buildings)
	
	#create humans
	humans = populate_city(250,canvas,root,buildings)
	
	#create the player and set it as the key listener
	player = Player(root,canvas,hud,buildings,zombies,humans)
	root.bind_all('<Key>',player.move)
	
	#ensure that the zombies and humans all know each other and the player
	for zombie in zombies:
		zombie.know_beings(humans,zombies,player)
	for human in humans:
		human.know_beings(humans,zombies,player)
	
	#set the initial values of some variables required for the pause screen
	head_text = ""
	was_paused = False
	
	#start our main game loop
	while(1):
		#if the game is paused...
		if player.paused:
			#...and within the last iteration of this loop, it was not:
			if not was_paused:
				#first ensure we have an empty menu array
				for i in range(len(player.menu_text)):
						player.canvas.delete(player.menu_text[i])
						
				#and create the main "Paused" header (and ensure that it is at the highest z-index)
				head_text = canvas.create_text((300,200),text="Paused",fill="#fff",font=("Helvectica", "24"))
				canvas.tag_raise(head_text)
				
				#iterate through the available menu items and print them, selecting the first item
				y = 240
				for menu_item in player.menu_items:
					#if this is the first iteration...
					if y == 240:
						#set the color to green (hilighted)
						color = "#0f0"
					else:
						#else, use a grey (not hilighted)
						color = "#999"
					
					#make the text, raise it, and add the instance to an array
					text = canvas.create_text((300,y),text=menu_item,fill=color,font=("Helvectica", "16"))
					canvas.tag_raise(text)
					player.menu_text.append(text)
					y+=20
					
			#else if the selected menu item has been changed...
			elif player.current_menu_item != player.last_menu_item:
				#first clear out the menu items so that we can update hilighting
				for i in range(len(player.menu_text)):
						canvas.delete(player.menu_text[i])
				player.menu_text = []
				y = 240
				
				#iterate through the available menu items and print them, selecting the current item
				for menu_item in player.menu_items:
					#if this is the current item...
					if menu_item == player.menu_items[player.current_menu_item]:
						#set the color to green (hilighted)
						color = "#0f0"
					else:
						#else, use a grey (not hilighted)
						color = "#999"
					
					#make the text, raise it, and add the instance to an array
					text = canvas.create_text((300,y),text=menu_item,fill=color,font=("Helvectica", "16"))
					canvas.tag_raise(text)
					player.menu_text.append(text)
					y+=20
				
				#keep a reference to this iteration's current menu item
				player.last_menu_item = player.current_menu_item
			
			#make sure that the root shows the most current view
			root.update()
			
			#and acknowledge that the game is now paused
			was_paused = True
		else:
			#if the game was paused in the last loop...
			if was_paused:
				#first, clean up the screen
				canvas.delete(head_text)
				for i in range(len(player.menu_text)):
						canvas.delete(player.menu_text[i])
				player.menu_text = []
				root.update()
			
			''' End-Game Scenarios '''
			
			#if every human is dead and the player is a zombie, break this loop
			if len(humans) == 0 and player.zombified:
				break
			#if every zombie is dead (and the player is not a zombie), break
			elif len(zombies) == 0 and not player.zombified:
				break
			#if the player is dead, break
			elif player.health_stage == 'dead':
				break
			#if the player chose "reset city," break
			elif player.menu_items[player.current_menu_item] == 'reset city':
				break
			
			#update the player's state - this also updates the player's weapons
			player.update()
			
			#move each zombie, then each human (this ensures that zombies can eventually catch humans)
			for zombie in zombies:
				zombie.move()
			for human in humans:
				human.move()
			
			#update root, then note that the game is not paused
			root.update()
			was_paused = False
	
	#store the score as a local variable so that when we delete the player, we don't lose it
	score = player.score
	
	#play the shotgun sound - it makes the transition seem less abrupt
	sound = mixer.Sound("shotgun.ogg")
	sound.set_volume(.5)
	sound.play()
	
	#if there are still humans, this is a human victory
	if len(humans) > 0:
		image = PhotoImage(file="human_vict.gif")
		
	#else, it is a zombie victory
	else:
		image = PhotoImage(file="zombie_vict.gif")
	
	#clear out the canvas and HUD
	canvas.pack_forget()
	canvas.destroy()
	hud.pack_forget()
	hud.destroy()
	
	#delete all of our arrays to free up memory
	del humans
	del zombies
	del player
	del buildings
	
	#make a new "game over" canvas and place our game over image along with the score
	canvas = Canvas(root, width=600, height=400, background="#000")
	canvas.pack(side='top')
	game_over_image = PhotoImage(file="title_screen_sm.gif")
	canvas.create_image((300,200),image=image)
	score_text = "Final Score: %d Points" % score
	canvas.create_text((300,360),text=score_text,fill="#fff",font=("Helvectica", "16"))
	canvas.create_text((300,384),text="Press Space To Replay",fill="#fff",font=("Helvectica", "12"))
	
	#set a listener linked to the function, "replay_trigger" via lambda function
	root.bind_all('<Key>',lambda event: replay_trigger(event,root,canvas))
	
	#keep the root window open
	root.mainloop()
	
def replay_trigger(event,root,canvas):
	#really we only care about the space bar (and enter key) at this point... anything else will just be ignored
	if event.keysym == 'space' or event.keysym == 'Return':
		#cool! they pressed space (or Enter) - signal the "groan" sound and transition
		mixer.Sound("groan.wav").play()
		
		#gonna fade out... sort of.
		fade_image = PhotoImage(file="fade25.gif")
		canvas.tag_raise(canvas.create_image((300,200),image=fade_image))
		root.update()
		sleep(.01)
		
		fade_image = PhotoImage(file="fade50.gif")
		canvas.tag_raise(canvas.create_image((300,200),image=fade_image))
		root.update()
		sleep(.01)
		
		fade_image = PhotoImage(file="fade75.gif")
		canvas.tag_raise(canvas.create_image((300,200),image=fade_image))
		root.update()
		sleep(.01)
		
		#we will now remove our 'game over' canvas and re-initialize the game
		canvas.pack_forget()
		canvas.destroy()
		canvas = Canvas(root, width=600, height=400, background="#000")
		canvas.pack(side='top')
		root.update()
		sleep(.1)
		canvas.pack_forget()
		canvas.destroy()
		initialize_window(root)
	
def build_city(number,parent):
	building_list = []
	for i in range(number):
		building_list.append(Building(parent))
	return building_list

def populate_city(number,parent,root,buildings):
	human_list = []
	for i in range(number):
		human_list.append(Human(root,parent,buildings))
	return human_list
	
def place_zombies(number,parent,root,buildings):
	zombie_list = []
	for i in range(number):
		zombie_list.append(Zombie(root,parent,buildings))
	return zombie_list